package cn.net.shuxing.yifu.common.service;

import cn.net.shuxing.yifu.common.bean.*;
import cn.net.shuxing.yifu.common.constant.*;
import cn.net.shuxing.yifu.common.dto.BaseDto;
import cn.net.shuxing.yifu.common.mapper.UserTransferMapper;
import cn.net.shuxing.yifu.common.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
@Transactional
public class UserTransferService extends HistoryService<UserTransfer, UserTransferMapper> {
    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UserRealInfoService userRealInfoService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserCapitalService userCapitalService;

    @Autowired
    private DealParamService dealParamService;

    @Autowired
    private FeeService feeService;

    @Autowired
    private DealHistoryService dealHistoryService;

    @Autowired
    private UserDealHistoryService userDealHistoryService;

    @Autowired
    private JedisUtil jedisUtil;

    @Autowired
    private AliveCoinActivateHistoryService aliveCoinActivateHistoryService;

    @Autowired
    private FrontCommonService frontCommonService;

    @Autowired
    private UserTransferMapper userTransferMapper;

    @Autowired
    private ShortService shortService;


    public List<UserTransfer> getsByUserId(Integer userId) {
        Example example = new Example(UserTransfer.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.orEqualTo("senderId", userId);
        criteria.orEqualTo("receiverId", userId);
        List<UserTransfer> userTransferList = getsByExample(example);
        return userTransferList;
    }

    public List<UserTransfer> getsUserTransfer(Integer userId) {
        Example example = new Example(UserTransfer.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.orEqualTo("senderId", userId);
        List<UserTransfer> userTransferList = getsByExampleWithoutComplete(example);
        return userTransferList;
    }

//    public List<UserTransfer> getsByUserIdAndDayCount(int shareholderId, int count) {
//        TimeExample example = new TimeExample(getBeanClass());
//        example.equals("shareholderId", shareholderId);
//        example.dayGreaterThan("createTime", count);
//        return mapper.selectByExample(example);
//    }


    public BaseDto activateNewWallet(Integer senderId, Integer receiverId, Integer coinTypeId, BigDecimal count) {
        BigDecimal activateWalletNeedMinCount = new BigDecimal(dealParamService.getValue(senderId, coinTypeId, UserParamConst.ACTIVATE_WALLET_NEED_MIN_COUNT));
        BigDecimal activateWalletNeedMaxCount = new BigDecimal(dealParamService.getValue(senderId, coinTypeId, UserParamConst.ACTIVATE_WALLET_NEED_MAX_COUNT));

        if (count.compareTo(activateWalletNeedMinCount) < 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("转账数量过低,无法激活用户");
            return baseDto;
        }
        if (count.compareTo(activateWalletNeedMaxCount) > 0) {
            BaseDto baseDto = new BaseDto();
            baseDto.setCode(CodeConst.ERROR);
            baseDto.setMsg("转账数量过高,无法激活用户");
            return baseDto;
        }


        /** 转账 **/
        UserCapital senderUserCapital = userCapitalService.getByUserIdAndCoinTypeIdAndUserType(senderId, coinTypeId, UserType.SHAREHOLDER);
        BigDecimal aliveCoinCount = senderUserCapital.getAliveCoinCount();
        BigDecimal sleepCoinCount = senderUserCapital.getSleepCoinCount();
        /** 先看股东钱包总额是否足够支付该笔转账 **/
        if (aliveCoinCount.add(sleepCoinCount).compareTo(count) < 0)
            return BaseDto.error("钱包余额不足以支付这笔转账");

        /** 如果股东活币足够则直接用活币转 **/
        if (aliveCoinCount.compareTo(count) >= 0) {
            userCapitalService.reduceAliveCoin(senderId, coinTypeId, count, UserType.SHAREHOLDER);
            /** 插入激活记录 **/
            AliveCoinActivateHistory aliveCoinActivateHistory = new AliveCoinActivateHistory();
            aliveCoinActivateHistory.setMemberId(receiverId);
            aliveCoinActivateHistory.setShareholderId(senderId);
            aliveCoinActivateHistory.setCoinTypeId(coinTypeId);
            aliveCoinActivateHistory.setCount(count);
            aliveCoinActivateHistory.setType(0);
            aliveCoinActivateHistoryService.insert(aliveCoinActivateHistory);
        } else {
            return BaseDto.error("钱包余额不足");
        }

        /** 初始化新钱包 **/
        userCapitalService.insert(receiverId, coinTypeId, null, new BigDecimal(0), new BigDecimal(0), UserType.MEMBER);

        /** 新钱包收钱 **/
        userCapitalService.addAliveCoin(receiverId, coinTypeId, count, UserType.MEMBER);
        userCapitalService.addDealCount(receiverId, coinTypeId, count);
        userCapitalService.addDealCount(receiverId, coinTypeId, count, UserType.SHAREHOLDER);

        /** 将交易记录存放在表中 **/
        Integer dealScene = DealScene.SHAREHOLDER_TRANSFER_NEWMEMBER;
        //Jedis //jedis = jedisUtil.getJedis();
        BigDecimal openPrice = new BigDecimal(jedisUtil.get(RedisKeyCreator.openPrice(coinTypeId)));
        //jedisUtil.close();
//        dealHistoryService.insert(senderId, receiverId, null, null, DealScene.MEMBER_TRANSFER, coinTypeId, openPrice, count);
        String orderNo = userDealHistoryService.createOrderNo(8);
        userDealHistoryService.insert(senderId, coinTypeId, DealType.TRANSFER_OUT, DealScene.NONE, count, openPrice, UserType.SHAREHOLDER, orderNo);
        userDealHistoryService.insert(receiverId, coinTypeId, DealType.TRANSFER_IN, DealScene.NONE, count, openPrice, UserType.NONE, orderNo);
        insert(senderId, receiverId, coinTypeId, count);

        User receiver = userService.getByPrimaryKey(receiverId);

        /** 获取激活时间 **/
        String activateTime = dealParamService.getValue(receiverId, coinTypeId, UserParamConst.ACTIVATE_TIME);
        Integer activateHours = Integer.valueOf(activateTime);

        /** 开启激活定时任务 **/
        userService.activateUser(receiverId, activateHours);
        BaseDto baseDto = new BaseDto();
        baseDto.setData("激活设置完成");

        return baseDto;
    }

    public String insert(Integer senderId, Integer receiverId, Integer coinTypeId, BigDecimal count) {
        String id = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + UUID.randomUUID().toString().substring(0, 18);
        UserTransfer userTransfer = new UserTransfer();
        userTransfer.setId(id);
        userTransfer.setSenderId(senderId);
        userTransfer.setReceiverId(receiverId);
        userTransfer.setTransferCoinTypeId(coinTypeId);
        userTransfer.setTransferCount(count);
        insert(userTransfer);
        return userTransfer.getId();
    }

    public BaseDto transfer(Integer senderId, Integer receiverId, Integer coinTypeId, BigDecimal count, Integer dealScene) {
//        Integer senderType = userService.getByPrimaryKey(senderId).getType();
//        Integer receiverType = userService.getByPrimaryKey(receiverId).getType();
        Integer senderType = 0;
        Integer receiverType = 0;

        if (dealScene == DealScene.MEMBER_TRANSFER_MEMBER) {
            senderType = UserType.MEMBER;
            receiverType = UserType.MEMBER;
        }
        if (dealScene == DealScene.SHAREHOLDER_TRANSFER_SHAREHOLDER) {
            senderType = UserType.SHAREHOLDER;
            receiverType = UserType.SHAREHOLDER;
        }
        if (dealScene == DealScene.SHAREHOLDER_TRANSFER_NEWMEMBER) {
            senderType = UserType.SHAREHOLDER;
            receiverType = UserType.MEMBER;
        }

        if (!frontCommonService.isWalletLeftCountEnough(senderId, coinTypeId, count))
            return BaseDto.error("转账用户钱包余额不足");
        if (!frontCommonService.isWalletLeftCountEnoughMaxKeep(receiverId, coinTypeId, count))
            return BaseDto.error("转账后会导致收账用户钱包余额高于交易钱包最大持有余额,转账失败");
        if (senderType == UserType.SHAREHOLDER) {
            Fee fee = feeService.getFee(senderId, coinTypeId, dealScene);
            if (count.compareTo(fee.getBaseDealCount()) >= 0) {
                BigDecimal feeCount = (count.subtract(fee.getBaseDealCount())).multiply(fee.getFeeRatio());
                BigDecimal newCount = count.add(feeCount);
                if (!frontCommonService.isWalletLeftCountEnoughMinKeep(senderId, coinTypeId, newCount))
                    return BaseDto.error("转账后会导致转账用户钱包余额低于交易钱包最小持有余额,转账失败");
            }

        }

        if (senderType == UserType.MEMBER) {
            /** 看坐空 **/
            /** 看是否需要使用坐空 **/
            UserCapital userCapital = userCapitalService.getByUserIdAndCoinTypeId(senderId, coinTypeId);
            if (userCapital == null)
                return BaseDto.error("钱包里此币种余额为0");
            BigDecimal walletCount = userCapital.getAliveCoinCount();

            /** 获取交易钱包最小活币量 **/
            String dealWalletMinCountStr = dealParamService.getValue(senderId, coinTypeId, UserParamConst.MEMBER_KEEP_ALIVE_COIN_MIN_COUNT);
            BigDecimal dealWalletMinCount = new BigDecimal(dealWalletMinCountStr);

            if ((walletCount.subtract(count)).compareTo(dealWalletMinCount) < 0) {
                Integer userShortCount = shortService.getUserShortCount(senderId, coinTypeId);
                Integer userShortDeadline = shortService.getUserShortDeadline(senderId, coinTypeId);
                if (userShortCount <= 0) {
                    Fee fee = feeService.getFee(senderId, coinTypeId, dealScene);
                    if (count.compareTo(fee.getBaseDealCount()) >= 0) {
                        BigDecimal feeCount = (count.subtract(fee.getBaseDealCount())).multiply(fee.getFeeRatio());
                        BigDecimal newCount = count.add(feeCount);
                        if (!frontCommonService.isWalletLeftCountEnoughMinKeep(senderId, coinTypeId, newCount))
                            return BaseDto.error("转账后会导致转账用户钱包余额低于交易钱包最小持有余额,转账失败");
                    }
                } else {
                    /** 使用坐空 **/
                    if (!shortService.insertShort(senderId, coinTypeId, userShortCount - 1, userShortDeadline)) {
                        shortService.updateShort(senderId, coinTypeId, userShortCount - 1, userShortDeadline);
                        Jedis jedis1 = jedisUtil.getJedis();
                        jedis1.set(RedisKeyCreator.shortStartTime(senderId), LocalDateTime.now().toString());
                        jedis1.close();
                    }
                }
            }
        }

        /** 转账 **/
        userCapitalService.reduceAliveCoin(senderId, coinTypeId, count, senderType);
        userCapitalService.addAliveCoin(receiverId, coinTypeId, count, receiverType);

        userCapitalService.addDealCount(senderId, coinTypeId, count, senderType);
        userCapitalService.addDealCount(receiverId, coinTypeId, count, receiverType);

        /** 交易记录存放在表中 **/
        /** 将交易记录存放在表中 **/
        //Jedis //jedis = jedisUtil.getJedis();
        BigDecimal openPrice = new BigDecimal(jedisUtil.get(RedisKeyCreator.openPrice(coinTypeId)));
        //jedisUtil.close();
//        dealHistoryService.insert(senderId, receiverId, null, null, dealScene, coinTypeId, openPrice, count);
//        String uuid = UUID.randomUUID().toString();

        String orderNo = userDealHistoryService.createOrderNo(8);
        userDealHistoryService.insert(senderId, coinTypeId, DealType.TRANSFER_OUT, DealScene.NONE, count, openPrice, senderType, orderNo);
        userDealHistoryService.insert(receiverId, coinTypeId, DealType.TRANSFER_IN, DealScene.NONE, count, openPrice, receiverType, orderNo);

        String insert = insert(senderId, receiverId, coinTypeId, count);
        UserTransfer userTransfer = userTransferMapper.selectById(insert);

        /** 手续费 **/
        Fee fee = feeService.getFee(senderId, coinTypeId, dealScene);
        if (count.compareTo(fee.getBaseDealCount()) >= 0) {
            BigDecimal feeCount = (count.subtract(fee.getBaseDealCount())).multiply(fee.getFeeRatio());
            feeService.reduceFee(senderId, coinTypeId, dealScene, count, openPrice, senderType);
            userDealHistoryService.insert(senderId, coinTypeId, DealType.FEE, dealScene, feeCount, new BigDecimal(0), senderType, orderNo);
        }
        return BaseDto.ok(userTransfer);
    }

    @Override
    public UserTransfer getByPrimaryKey(Object key) {
        CommonExample example = new CommonExample(UserTransfer.class);
        example.equals("id", key);
        return getByExampleWithoutComplete(example);
    }

    public List<UserTransfer> getTotalByUserId(Integer userId) {
        List<UserTransfer> userTransfers = getsByUserId(userId);
        return userTransfers;
    }

    public List<UserTransfer> getThisMonthByUserId(Integer userId) {
        TimeExample example = new TimeExample(UserTransfer.class);
        example.dayGreaterThan("createTime", LocalDate.now().getDayOfMonth());
        Example.Criteria criteria = example.getCriteria();
        criteria.orEqualTo("senderId", userId);
        criteria.orEqualTo("receiverId", userId);
        List<UserTransfer> userTransfers = getsByExampleWithoutComplete(example);
        return userTransfers;
    }

    public BigDecimal getTotalTransByUserId(Integer userId) {
        BigDecimal totalTrans = new BigDecimal(0);
        Example example = new Example(UserTransfer.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("senderId", userId);
        List<UserTransfer> userTransfers = getsByExampleWithoutComplete(example);
        if (userTransfers.size() != 0) {
            for (UserTransfer transfer : userTransfers) {
                totalTrans = totalTrans.add(transfer.getTransferCount());
            }
        }

        return totalTrans;
    }

    public BigDecimal getMonthTransferByUserId(Integer userId) {
        TimeExample example = new TimeExample(UserTransfer.class);
        example.equals("senderId", userId);
        Example.Criteria criteria = example.getCriteria();
        criteria.andGreaterThanOrEqualTo("createTime", LocalDateTimeUtil.getThisMonthFirstDay());
        List<UserTransfer> userTransfers = getsByExampleWithoutComplete(example);
        BigDecimal monthTransfer = new BigDecimal(0);
        if (userTransfers == null || userTransfers.isEmpty()) {
            return monthTransfer;
        } else {
            for (UserTransfer userTransfer : userTransfers) {
                monthTransfer = monthTransfer.add(userTransfer.getTransferCount());
            }
            return monthTransfer;
        }

    }

    @Override
    protected void complete(UserTransfer bean) {
        if (bean == null)
            return;
        Integer senderId = bean.getSenderId();
        String realName = "";
        UserRealInfo userRealInfo = userRealInfoService.getByPrimaryKey(senderId);
        if (userRealInfo != null) {
            realName = userRealInfo.getRealName();
        }

        bean.setSenderName(realName);
        Integer receiverId = bean.getReceiverId();
        userRealInfo = userRealInfoService.getByPrimaryKey(receiverId);
        if (userRealInfo == null) {
            bean.setReceiverName(userService.getByPrimaryKey(receiverId).getUsername());
        } else {
            bean.setReceiverName(userRealInfo.getRealName());
        }
    }

    public BigDecimal getThisMonthCountByUserId(Integer userId) {
        List<UserTransfer> userTransfers = getThisMonthByUserId(userId);
        BigDecimal thisMonthTransfer = new BigDecimal(0);
        if (userTransfers == null || userTransfers.isEmpty()) {
        } else {
            for (UserTransfer userTransfer : userTransfers) {
                thisMonthTransfer = thisMonthTransfer.add(userTransfer.getTransferCount());
            }
        }
        return thisMonthTransfer;
    }

    public BigDecimal getTransferByUserType(Integer shareholderId, Integer userType) {
        CommonExample commonExample = new CommonExample(UserTransfer.class);
        commonExample.equals("senderId", shareholderId);
        List<UserTransfer> userTransfers = getsByExampleWithoutComplete(commonExample);

        BigDecimal transfer = new BigDecimal(0);
        if (userTransfers == null || userTransfers.isEmpty()) {
        } else {
            for (UserTransfer userTransfer : userTransfers) {
                Integer receiverId = userTransfer.getReceiverId();
                boolean b = userRoleService.hasRole(receiverId, userType);
                if (b) {
                    BigDecimal transferCount = userTransfer.getTransferCount();
                    transfer = transfer.add(transferCount);
                } else {
                    transfer = transfer.add(new BigDecimal(0));
                }
            }
        }
        return transfer;
    }

    public List<UserTransfer> getsTransferByUserType(Integer shareholderId, Integer userType) {
        CommonExample commonExample = new CommonExample(UserTransfer.class);
        commonExample.equals("senderId", shareholderId);
        List<UserTransfer> userTransfersBySenderId = getsByExample(commonExample);
        ArrayList<UserTransfer> userTransferList = new ArrayList<>();
        if (userTransfersBySenderId == null || userTransfersBySenderId.isEmpty()) {
            return null;
        } else {
            for (UserTransfer userTransfer : userTransfersBySenderId) {
                Integer receiverId = userTransfer.getReceiverId();
                if (userRoleService.hasRole(receiverId, userType)) {
                    userTransferList.add(userTransfer);
                }
            }
            return userTransferList;
        }
    }


    public List<UserTransfer> getByUserIdAndDealType(Integer userId, int transferIn) {
        CommonExample commonExample = new CommonExample(UserTransfer.class);
        commonExample.equals("recieverId", userId);
        return getsByExampleWithoutComplete(commonExample);
    }

    public List<UserTransfer> getsTosTransfer(Integer userId) {
        CommonExample commonExample = new CommonExample(UserTransfer.class);
        commonExample.equals("senderId", userId);
        List<UserTransfer> userTransfers = getsByExampleWithoutComplete(commonExample);
        ArrayList<UserTransfer> userTransList = new ArrayList<>();
        if (userTransfers == null || userTransfers.isEmpty()) {
        } else {
            for (UserTransfer userTransfer : userTransfers) {
                Integer receiverId = userTransfer.getReceiverId();
                if (userRoleService.hasRole(receiverId, UserType.SHAREHOLDER)) {
                    userTransList.add(userTransfer);
                }
            }
        }
        return userTransList;
    }

}
